package com.example.suota.suota;

import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGattCharacteristic;
import android.content.Context;
import android.util.Log;

import androidx.annotation.NonNull;

import com.example.suota.suota.global.SuotaLibConfig;
import com.example.suota.suota.global.SuotaProfile;
import com.example.suota.suota.interfaces.callbacks.ISuotaScanner;
import com.example.suota.suota.scan.XLSuotaScanner;
import com.example.suota.suota.suota.SuotaFile;
import com.example.suota.suota.suota.SuotaManager;
import com.example.suota.suota.suota.SuotaManagerCallback;

import java.util.HashMap;
import java.util.Map;

import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.MethodChannel.Result;
import io.flutter.plugin.common.EventChannel;
import android.text.TextUtils;
/** SuotaPlugin */
public class SuotaPlugin implements FlutterPlugin, MethodCallHandler {
  /// The MethodChannel that will the communication between Flutter and native Android
  ///
  /// This local reference serves to register the plugin with the Flutter Engine and unregister it
  /// when the Flutter Engine is detached from the Activity
  private MethodChannel channel;

  private Context currentContext;
  // 事件派发对象
  private  EventChannel.EventSink eventSink = null;

  private XLSuotaScanner suotaScanner;
  private SuotaManager suotaManager;
  private String name;
  private String filePath;
  private String fileName;
  private boolean isConnecting  = false;

  private  EventChannel.StreamHandler streamHandler = new  EventChannel.StreamHandler(){
    @Override
    public void onListen(Object arguments, EventChannel.EventSink events) {
      eventSink = events;
    }

    @Override
    public void onCancel(Object arguments) {
      eventSink = null;
    }
  };

  @Override
  public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) {
    channel = new MethodChannel(flutterPluginBinding.getBinaryMessenger(), "suota");
    channel.setMethodCallHandler(this);

    //获取currentContext
    currentContext = flutterPluginBinding.getApplicationContext();

    // 初始化事件
    EventChannel eventChannel = new EventChannel(flutterPluginBinding.getBinaryMessenger(), "updateEventChannel");
    eventChannel.setStreamHandler(streamHandler);
  }

  @Override
  public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
//    if (call.method.equals("getPlatformVersion")) {
//      result.success("Android " + android.os.Build.VERSION.RELEASE);
//    } else {
//      result.notImplemented();
//    }

    if (call.method.equals("getPlatformVersion")) {
      result.success("Android release " + android.os.Build.VERSION.RELEASE);
    } else if (call.method.equals("startUpdate")){

      Log.d("SuotaPlugin", "The onCreate() event");
      Log.d("SuotaPlugin", call.arguments.toString());
      Map getresult = (Map) call.arguments;
      Log.d("SuotaPluginMap", getresult.toString());
//      eventSink.success(getresult);
      name = (String) getresult.get("name");
      filePath = (String) getresult.get("filePath");
      if (!TextUtils.isEmpty(filePath)){
        int index = filePath.lastIndexOf("/");
        if (index != -1 && index < filePath.length()){
            fileName = filePath.substring(index+1);
            filePath = filePath.substring(0,index);
        }
      }
      
      Log.d("SuotaPlugin", "filePath = "+filePath);
      Log.d("SuotaPlugin", "fileName = "+fileName);


      scan(currentContext.getApplicationContext());
//      result.success("Android " + "startUpdate");
    } else {
      result.notImplemented();
    }
  }

  @Override
  public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
    channel.setMethodCallHandler(null);
  }

  /**
   * 开始扫描蓝牙
   * @param context
   */
  public void scan(Context context){
    if (suotaScanner == null) {
      suotaScanner = new XLSuotaScanner(context);
    }
    suotaScanner.scan(new ISuotaScanner() {
      @Override
      public void onFailure(SuotaProfile.ScanFailure failure) {
        //扫描失败
        Log.d("SuotaPlugin", "fail");
        isConnecting = false; 
      }

      @Override
      public void onDeviceScan(BluetoothDevice bluetoothDevice, int rssi, byte[] scanRecord) {
        //扫描到设备
        Log.d("SuotaPlugin", name);
        Log.d("SuotaPlugin", name.toUpperCase());
        Log.d("SuotaPlugin", bluetoothDevice.getName());
        // if(name.equals(bluetoothDevice.getName()) && !isConnecting){
        //   isConnecting = true;
        //   connect(context.getApplicationContext(), bluetoothDevice);

        // }
        
        if(null != name && name.equals(bluetoothDevice.getName()) && !isConnecting){
          isConnecting = true;
          connect(context.getApplicationContext(), bluetoothDevice);
          stopScan();
        }
      }

      @Override
      public void onScanStatusChange(SuotaProfile.ScanStatus newStatus) {
        //扫描状态变化
        Log.d("SuotaPlugin", "onScanStatusChange");
        Log.d("SuotaPlugin", String.valueOf(newStatus));
        if(SuotaProfile.ScanStatus.STOPPED == newStatus){
          isConnecting = false;
        }
      }
    });
  }


  public boolean isScanning(){
    if (suotaScanner != null) {
      return suotaScanner.isScanning();
    }
    return false;
  }

  /**
   * 停止扫描蓝牙设备
   */
  public void stopScan(){
    if (suotaScanner != null) {
      suotaScanner.stopScan();
    }
  }

  /**
   * 销毁蓝牙扫描
   */
  public void destroyScan() {
    if (suotaScanner != null) {
      suotaScanner.destroy();
    }
  }


  /**
   * 连接蓝牙
   * @param context
   * @param bluetoothDevice
   */
  public void connect(Context context,BluetoothDevice bluetoothDevice) {
    suotaManager = new SuotaManager(context, bluetoothDevice, null);
    setFilePath(filePath,fileName);
    suotaManager.setSuotaManagerCallback(new SuotaManagerCallback() {
      @Override
      public void onConnectionStateChange(SuotaProfile.SuotaManagerStatus newStatus) {
        super.onConnectionStateChange(newStatus);
        //连接状态变化
        if (newStatus != SuotaProfile.SuotaManagerStatus.DISCONNECTED)
          return;
        if (eventSink != null) {
            Map<String,String> map = new HashMap<>();
            map.put("onManagerFailure","手环手动断了连接");
            eventSink.success(map);
          }
      }

      @Override
      public void onServicesDiscovered() {
        super.onServicesDiscovered();
      }

      @Override
      public void onCharacteristicRead(SuotaProfile.CharacteristicGroup characteristicGroup, BluetoothGattCharacteristic characteristic) {
        super.onCharacteristicRead(characteristicGroup, characteristic);

      }

      @Override
      public void onDeviceInfoReadCompleted(SuotaProfile.DeviceInfoReadStatus status) {
        super.onDeviceInfoReadCompleted(status);

      }

      @Override
      public void updateSpeedStatistics(double current, double max, double min, double avg) {
        super.updateSpeedStatistics(current, max, min, avg);

      }

      @Override
      public void updateCurrentSpeed(double currentSpeed) {
        super.updateCurrentSpeed(currentSpeed);
      }

      @Override
      public void onDeviceReady() {
        super.onDeviceReady();
        startUpdate();

      }

      @Override
      public void onSuotaLog(SuotaProfile.SuotaProtocolState state, SuotaLogType type, String log) {
        super.onSuotaLog(state, type, log);
      }

      @Override
      public void onChunkSend(int chunkCount, int totalChunks, int chunk, int block, int blockChunks, int totalBlocks) {
        super.onChunkSend(chunkCount, totalChunks, chunk, block, blockChunks, totalBlocks);
      }

      @Override
      public void onBlockSent(int block, int totalBlocks) {
        super.onBlockSent(block, totalBlocks);

      }

      @Override
      public void onUploadProgress(float percent) {
        super.onUploadProgress(percent);
        int process =(int)(percent);

        //更新进度，百分比
        if (eventSink != null) {
          Map<String,String> map = new HashMap<>();
          map.put("process",process+"");
          eventSink.success(map);
        }

      }

      @Override
      public void onSuccess(double totalElapsedSeconds, double imageUploadElapsedSeconds) {
        super.onSuccess(totalElapsedSeconds, imageUploadElapsedSeconds);
        //更新成功
        Map<String,String> map = new HashMap<>();
        map.put("onSuccess","0");
        eventSink.success(map);
        eventSink = null;
        //需要重启
        // sendRebootCommand();
        destroy();


      }

      @Override
      public void onFailure(int errorCode) {
        super.onFailure(errorCode);
        //更新失败
        Map<String,String> map = new HashMap<>();
        map.put("onManagerFailure",errorCode+"");
        eventSink.success(map);
        destroy();

      }

      @Override
      public void onRebootSent() {
        super.onRebootSent();
        //todo 发送设备重启指令
      }
    });
    suotaManager.connect();
  }


  public void disConnect(){
    if (suotaManager != null) {
      suotaManager.disconnect();
    }
  }

  public void destroy(){
    if (suotaManager != null) {
      suotaManager.destroy();
    }
  }

  public SuotaManager getSuotaManager() {
    return suotaManager;
  }

  /**
   * 设置 固件文件路径
   * @param path
   * @param fileName
   */
  public void setFilePath(String path,String fileName){
    if (suotaManager != null) {
      SuotaFile suotaFile = new SuotaFile(path, fileName);
      suotaManager.setSuotaFile(suotaFile);
    }
  }

  public void setFilePath(SuotaFile suotaFile){
    if (suotaManager != null) {
      suotaManager.setSuotaFile(suotaFile);
    }
  }

  /**
   * 开始固件升级
   */
  public void startUpdate(){
    if (suotaManager != null) {
      suotaManager.initializeSuota(
              SuotaLibConfig.Default.BLOCK_SIZE,
              SuotaLibConfig.Default.MISO_GPIO,
              SuotaLibConfig.Default.MOSI_GPIO,
              SuotaLibConfig.Default.CS_GPIO,
              SuotaLibConfig.Default.SCK_GPIO,
              SuotaLibConfig.Default.IMAGE_BANK);

      suotaManager.startUpdate();
    }
  }
  /**
   * 重启设备
   */
  public void sendRebootCommand() {
    if (suotaManager != null) {
      suotaManager.sendRebootCommand();
    }
  }

}
